#!/usr/bin/env python
# coding: utf-8

# In[506]:


import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import linear_kernel
from collections import Counter
from spellchecker import SpellChecker
import ast
import re


# In[507]:


merged_data = pd.read_csv("updata/merge_data.csv", na_filter=False)


# 对输入的语句的正确性处理

# In[508]:


# 输入新的电影名称
movie_title = "Indie Films"
# 使用正则表达式去除非字母字符
new_movie_title = re.sub(r'[^a-zA-Z0-9\s]', '', movie_title)

print(new_movie_title)


# In[509]:


# spell = SpellChecker()
# # 分词并尝试纠正每个单词，如果无法纠正就使用原单词
# corrected_words = []
# for word in new_movie_title.split():
#     try:
#         # 尝试纠正单词
#         corrected_word = spell.correction(word)
#         # 确保添加到列表的是字符串
#         corrected_words.append(corrected_word if corrected_word is not None else word)
#     except Exception as e:
#         # 如果发生错误，使用原单词并记录错误信息
#         corrected_words.append(word)
#         print(f"Error correcting word '{word}': {str(e)}")

# # 将纠正后的单词组合回一句完整的文本
# new_movie_title = ' '.join(corrected_words)

# print(new_movie_title)


# 文本相似度处理

# In[510]:


###首先根据title和overview计算


# In[511]:


from sklearn.feature_extraction.text import TfidfVectorizer

# 定义一个移除所有english stop words如'the', 'a'的转换器
tfidf = TfidfVectorizer(stop_words='english')

# 将标题和概述用空格隔开并存储到一个数组（列表）中
title_list = ((merged_data['title']+' ')*5+ ' '+ (merged_data['comb'])+' '+(merged_data['overview']+' ')).tolist()
#title_list = ((merged_data['title']+' ')*2+ ' '+ (merged_data['comb'])).tolist()

title_list.append(new_movie_title)

# 构建 TF-IDF 矩阵
tfidf = TfidfVectorizer(stop_words='english')
tfidf_matrix = tfidf.fit_transform(title_list)

# 输出矩阵形状
tfidf_matrix.shape


# 

# In[ ]:


# 获取词汇表
feature_names = tfidf.get_feature_names_out()

# 获取新电影的TF-IDF向量
new_movie_vector = tfidf_matrix[-1]

# 将TF-IDF向量转换为词素集合
new_movie_tokens = set(feature_names[i] for i in new_movie_vector.indices)

# 获取所有其他电影的词素集合
other_movie_tokens = set()
for doc in tfidf_matrix[:-1]:
    other_movie_tokens.update(feature_names[i] for i in doc.indices)

# 计算新电影词素集合中在其他电影词素集合中出现的词素集合
common_tokens = new_movie_tokens.intersection(other_movie_tokens)

# # 输出新电影词素集合中在其他电影词素集合中出现的词素集合
# print("新电影词素集合中在其他电影词素集合中出现的词素集合:")
# print(common_tokens)


# 请点击[此处](https://ai.baidu.com/docs#/AIStudio_Project_Notebook/a38e5576)查看本环境基本用法.  <br>
# Please click [here ](https://ai.baidu.com/docs#/AIStudio_Project_Notebook/a38e5576) for more detailed instructions. 

# In[ ]:


# 计算余弦相似度，仅计算新电影与其他电影的相似度
cosine_sim_1 = linear_kernel(tfidf_matrix[-1:], tfidf_matrix[:-1])

# 获取与新电影最相似的前20个电影
sim_scores_1 = list(enumerate(cosine_sim_1[0]))
# print(sim_scores_1[:5])
# sim_scores = sorted(sim_scores_1, key=lambda x: x[1], reverse=True)[:20]

# # 获取最相似电影的索引和相似度分数
# movie_indices = [i[0] for i in sim_scores]
# scores = [score[1] for score in sim_scores]

# # 输出推荐结果
# recommendations = merged_data['title'].iloc[movie_indices]
# for title, score in zip(recommendations, scores):
#     print(f"Title: {title}, Similarity Score: {score}")

# #将结果保存到文件
# output_df = pd.DataFrame({
#     'movieId': merged_data.iloc[movie_indices]['id'],
#     'title': merged_data.iloc[movie_indices]['title'],
#     'similarity_score': scores
# })
# output_df.to_csv('result/similar_movies.csv', index=False, header=True)

# print("Results saved to 'result/similar_movies.csv'")


# ###其次根据keywords计算

# In[ ]:


from sklearn.feature_extraction.text import TfidfVectorizer

# 定义一个移除所有english stop words如'the', 'a'的转换器
tfidf = TfidfVectorizer(stop_words='english')
# 清理 NaN 值，将其替换为空字符串
keywords_list = (merged_data['keywords']).tolist()
keywords_list.append(new_movie_title)
# # 打印前5个组合后的结果以进行验证
# print("前5个组合后的结果:", keywords_list[:5])

# 构建 TF-IDF 矩阵
tfidf = TfidfVectorizer(stop_words='english')
tfidf_matrix_2 = tfidf.fit_transform(keywords_list)

# 输出矩阵形状
tfidf_matrix_2.shape


# In[ ]:


# 获取词汇表
feature_names = tfidf.get_feature_names_out()

# 获取新keywords的TF-IDF向量
new_keywords_vector = tfidf_matrix_2[-1]

# 将TF-IDF向量转换为词素集合
new_keywords_tokens = set(feature_names[i] for i in new_keywords_vector.indices)

# 获取所有其他电影的词素集合
other_keywords_tokens = set()
for doc in tfidf_matrix_2[:-1]:
    other_keywords_tokens.update(feature_names[i] for i in doc.indices)

# 计算新电影词素集合中在其他电影词素集合中出现的词素集合
common_tokens_2 = new_keywords_tokens.intersection(other_keywords_tokens)

# 输出新电影词素集合中在其他电影词素集合中出现的词素集合
print("新关键词素集合中在其他电影词素集合中出现的词素集合:")
print(common_tokens_2)


# In[ ]:


# 计算余弦相似度，仅计算新电影与其他关键词的相似度
cosine_sim_2 = linear_kernel(tfidf_matrix_2[-1:], tfidf_matrix_2[:-1])


# In[ ]:


###把他们合起来


# In[ ]:


# 计算两个集合的交集
intersection_tokens = common_tokens.intersection(common_tokens_2)

# 输出两个集合的交集
print("两个集合的交集:")
print(intersection_tokens)


# In[ ]:


##计算集合的并集
# 使用 union() 方法
union_set = common_tokens.union(common_tokens_2)
union_set = union_set.union(intersection_tokens)
# 输出两个集合的交集
print("两个集合的并集:")
print(intersection_tokens)


# In[ ]:


print(len(common_tokens_2))
print(len(common_tokens))
print(len(intersection_tokens))
print(len(union_set))
print(len(new_movie_tokens))
print(new_movie_tokens)


# #做一个合并

# In[ ]:


##计算参数的方法
if(len(common_tokens_2)==len(intersection_tokens)==len(union_set)):
    C2 = 0.5
elif(len(common_tokens_2)==len(intersection_tokens)==0):
    C2 = 0
elif(len(common_tokens)==len(intersection_tokens)==0):
    C2 = 1
else:
    C2 = (len(common_tokens_2)+len(intersection_tokens)/2)/(len(common_tokens)+len(common_tokens_2))
print(C2)


# In[ ]:


# 余弦结果获取与输入最相似的电影
sim_scores_1 = list(enumerate(cosine_sim_1[0]))
# 获余弦结果取与输入最相似的关键词
sim_scores_2 = list(enumerate(cosine_sim_2[0]))

# 计算加权平均相似度分数
# 每个相似度分数列表的权重都是0.5
combined_sim_scores = [(idx, (1-C2)* score1 + C2 * score2) for (idx, score1), (_, score2) in zip(sim_scores_1, sim_scores_2)]

# 对合并后的相似度分数进行排序，取得最相似的条目
combined_sim_scores = sorted(combined_sim_scores, key=lambda x: x[1], reverse=True)

# 筛选出分数大于0的条目
non_zero_scores = [item for item in combined_sim_scores if item[1] > 0]

# 对这些条目按分数进行降序排序
non_zero_scores.sort(key=lambda x: x[1], reverse=True)

top_n_indexes = [item[0] for item in non_zero_scores]

scores = [score[1] for score in non_zero_scores]

# 从merged_data中获取相应的id和title
top_n_data = merged_data.loc[top_n_indexes, ['id', 'title','popularity','vote_average','vote_count','ad']]

# 添加分数列
top_n_data['score'] = scores  # 直接添加列
top_n_data = top_n_data[:10]
# 显示结果
print(top_n_data)


# In[ ]:


# 第一步：将top_n_data的ID列转换为浮点数类型（处理小数形式）
top_n_data['id'] = pd.to_numeric(top_n_data['id'], errors='coerce')

# 第二步：删除无法转换为数值的ID（NaN）
top_n_data = top_n_data.dropna(subset=['id'])

# 第三步：将浮点数转换为整数类型（取整去掉小数部分）
top_n_data['id'] = top_n_data['id'].astype(int)

# 确保需要计算的列都是数值类型
columns_to_convert = ['popularity', 'vote_average', 'vote_count', 'score','ad']
for column in columns_to_convert:
    top_n_data[column] = pd.to_numeric(top_n_data[column], errors='coerce')

# 删除转换过程中出现的NaN值
top_n_data = top_n_data.dropna(subset=columns_to_convert)
print(top_n_data)


# 

# In[ ]:


# 定义映射范围和权重参数
mapping = {
    'popularity': {'range': (0, 10), 'weight': 0.5},
    'ad': {'range': (1, 1), 'weight': 0.1},
    'vote_average': {'range': (0, 10), 'weight': 1},
    'vote_count': {'range': (0, 10), 'weight': 0.1},
    'score': {'range': (0, 1), 'weight': 10}
}

def map_to_range(value, original_min, original_max, target_min, target_max):
    """ 将值从原始范围映射到目标范围 """
    original_range = original_max - original_min
    target_range = target_max - target_min
    if original_range == 0:
        original_range = target_min
    normalized_value = (value - original_min) / original_range  # 归一化到 [0, 1]
    mapped_value = target_min + (normalized_value * target_range)  # 映射到目标范围
    return mapped_value
# 初始化加权和列
top_n_data['weighted_sum'] = 0

# 原始范围可以从数据的实际最小值和最大值中计算
for column, params in mapping.items():
    target_min, target_max = params['range']
    weight = params['weight']
    original_min = top_n_data[column].min()
    original_max = top_n_data[column].max()
    
    # 映射值并计算加权和
    top_n_data['weighted_sum'] += map_to_range(top_n_data[column], original_min, original_max, target_min, target_max) * weight
    #print( map_to_range(top_n_data[column], original_min, original_max, target_min, target_max))

# 根据加权和排序
data_sorted = top_n_data.sort_values(by='weighted_sum', ascending=False)

# 输出排序后的数据
print(data_sorted[['id', 'title', 'weighted_sum']])


# In[ ]:


# 提取 id 列
id_list = data_sorted['id'].tolist()

# 输出 id 列表
print(id_list)


# In[ ]:


try:
    get_ipython().system('jupyter nbconvert --to python a')
except:
    pass

